﻿using System;
using System.Collections.Generic;
using System.Text;
using Castle.Windsor;
using Castle.Windsor.Configuration.Interpreters;
using Castle.MicroKernel;
using Castle.Core.Resource;
using System.Xml;
using System.IO;

namespace MyLib
{
    public class ServiceContainer
    {
        static ServiceContainer _inst=null;
        public static object obj = new object();
        public static ServiceContainer Instance()
        {
            lock (obj)
            {
                if (_inst == null)
                {
                    _inst = new ServiceContainer();
                }

                return _inst;
            }
        }

        public static void ClearInstance()
        {
            _inst = null;
        }

        IWindsorContainer _container;
        IWindsorContainer _childContainer;
        internal ServiceContainer()
        {
            IWindsorContainer container;
            object section = ConfigurationManager.GetSection("castle");
            if (section != null)
            {
                if (ConfigurationManager.ConfigFileType == ConfigFileType.FileConfig)
                {
                    MyConfigResource1 resource1 = new MyConfigResource1((XmlNode)section);
                    container = new WindsorContainer(new XmlInterpreter(resource1));
                }
                else
                {
                    container = new XmlContainer();
                }
            }
            else
            {
                //MyConfigResource resource = new MyConfigResource();
                //container = new WindsorContainer(new XmlInterpreter(resource));
                container = new WindsorContainer();
            }

            _container = container;
            _childContainer = new WindsorContainer();
            _container.AddChildContainer(_childContainer);
        }

        public void AddComponent(string key, Type serviceType, Type classType)
        {
            if (_childContainer != null)
            {
                _childContainer.AddComponent(key, serviceType, classType);
            }
            else if (_container != null)
            {
                _container.AddComponent(key, serviceType, classType);
            }
        }

        public IWindsorContainer Container
        {
            get { return _container; }
        }

        public IWindsorContainer ChildContainer
        {
            get { return _childContainer; }
        }

        public T GetService<T>() where T : class
        {
            T t = GetService<T>("");
            if (t == null)
            {
                throw new NotImplementedException(string.Format("Can not found the implementation of the interface {0}", typeof(T).ToString()));
            }
            return t;
        }

        public T GetService<T>(string id) where T : class
        {
            T t = default(T);
            if (string.IsNullOrEmpty(id))
            {
                t = _container.GetService<T>();
                if (t == null && _childContainer != null)
                {
                    t = _childContainer.GetService<T>();
                }
            }
            else
            {
                t = _container.Resolve<T>(id);
                if (t == null && _childContainer != null)
                {
                    t = _childContainer.Resolve<T>(id);
                }
            }

            return t;
        }

        public T GetService<T>(T defaultType) where T : class
        {
            T t = GetService<T>("");
            if (t == null)
            {
                t = defaultType;
            }
            if (t == null)
            {
                throw new NotImplementedException(string.Format("Can not found the implementation of the interface {0}", typeof(T).ToString()));
            }
            return t;
        }

        public T[] GetAll<T>() where T : class
        {
            T[] ts = _container.ResolveAll<T>();
            if (ts.Length == 0)
            {
                if (_childContainer != null)
                {
                    ts = _childContainer.ResolveAll<T>();
                }
            }
            return ts;
        }

        public void Release(object instance)
        {
            _container.Release(instance);
            if (_childContainer != null)
            {
                _childContainer.Release(instance);
            }
        }
    }

    internal class XmlContainer : WindsorContainer
    {
        public XmlContainer()
            : base(new XmlInterpreter())
        {
        }
    }
    
}
